#include "stdafx.h"
#include "PointsClassifier.h"
#include "math.h"
#include "comment.h" // opencv header

namespace ftips {

	PointsClassifier::PointsClassifier(int total) {
		m_classNum = 0;
		m_total = total;
	}

	// Function: to calculate dissimilarity between class center and new point
	int PointsClassifier::CalCenterDissimilarity(int classIndex, int point) {
		 return CalDissimilarity(point, m_classifier[classIndex][m_classCenters[classIndex]][0]);
	}

	// Function: to calculate dissimilarity(distance) between two points
	int PointsClassifier::CalDissimilarity(int point1, int point2) {
		int dis = abs(point1 - point2);
		return dis > (m_total - dis) ? (m_total - dis) : dis; // shorter distance on circle
	}

	// Function: to calculate new class center
	int PointsClassifier::CalCenter(int classIndex) {
		int minPos = m_classCenters[classIndex];
		for (int i = 0; i < m_individualNums[classIndex]; i++) {
			if (m_classifier[classIndex][i][1] < m_classifier[classIndex][m_classCenters[classIndex]][1])
				minPos = i;
		}
		return minPos;
	}

	// Function: to classify points with K-medoids
	void PointsClassifier::Kmedoids(int point) {
		int i = 0;
		for (; i < m_classNum; i++) {
			int dsml = CalCenterDissimilarity(i, point);
			if (dsml < DSML_UPPERBOUND) { 
				m_classifier[i][m_individualNums[i]][0] =  point; // insert point into class i
				m_classifier[i][m_individualNums[i]++][1] =  0;
				RefreshDis(i, point); // refresh point dissimilarity of class i
				m_classCenters[i] = CalCenter(i);
				break;
			}
		}
		if (i == m_classNum) 
			CreateNewClass(point);
	}

	// Function: to refresh point dissimilarity to others
	void PointsClassifier::RefreshDis(int classIndex, int point) {
		for (int i = 0; i < m_individualNums[classIndex] - 1; i++ ) {
			int dsml = CalDissimilarity(point, m_classifier[classIndex][i][0]);
			m_classifier[classIndex][i][1] += dsml;
			m_classifier[classIndex][m_individualNums[classIndex] - 1][1] += dsml;
		}
	}

	// Function: to create new class
	bool PointsClassifier::CreateNewClass(int point) {
		if (m_classNum == MAX_CLASS_NUM - 1)
			return false;
		m_classifier[m_classNum][0][0] = point;
		m_classifier[m_classNum][0][1] = 0;
		m_individualNums[m_classNum] = 1;
		m_classCenters[m_classNum] = 0;
		m_classNum++;
		return true;
	}

	// Function: get individual number of class
	int PointsClassifier::GetIndividualNum(int classIndex) {
		return m_individualNums[classIndex];
	}

	// Function: get center point value of class
	int PointsClassifier::GetClassCenter(int classIndex){
		return  m_classifier[classIndex][m_classCenters[classIndex]][0];
	}

	// Function: get all points' value of class
	void PointsClassifier::GetClassIndividualPoints(int classIndex, std::list<int> *pointsList) {
		for (int i = 0; i < m_individualNums[classIndex]; ++i)
			pointsList->push_back(m_classifier[classIndex][i][0]);
	}

	int PointsClassifier::GetClassNum() {
		return m_classNum;
	}

}